package com.colin.distributelock.lock;

import lombok.extern.slf4j.Slf4j;
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;

import java.io.IOException;
import java.util.Collections;
import java.util.List;

/**
 * Created by Colin on 2020/9/21 19:56
 * email: colinzhaodong@gmail.com
 * desc:
 *
 * @author zhaod
 */
@Slf4j
public class ZookeeperLock implements AutoCloseable, Watcher {
	private ZooKeeper zooKeeper;
	private String zNnode;

	public ZookeeperLock() throws IOException {
		this.zooKeeper = new ZooKeeper("127.0.0.1:2181", 10000, this);
	}

	public boolean getLock(String businessCode) {
		try {
			//创建业务根节点
			Stat stat = zooKeeper.exists("/" + businessCode, false);
			if (stat == null) {
				zooKeeper.create("/" + businessCode, businessCode.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
			}
			//创建瞬时有序节点 /order/order_0011
			zNnode = zooKeeper.create("/" + businessCode + "/" + businessCode + "_", businessCode.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
			//获取业务节点下的子节点
			List<String> children = zooKeeper.getChildren("/" + businessCode, false);
			//子节点排序
			Collections.sort(children);
			//获取第一个子节点
			String firstNode = children.get(0);
			if (zNnode.endsWith(firstNode)) {
				return true;
			}
			//不是第一个子节点,则监听前一个节点
			String lastNode = firstNode;
			for (String child : children) {
				if (zNnode.endsWith(child)) {
					zooKeeper.exists("/" + businessCode + "/" + lastNode, true);
					break;
				} else {
					lastNode = child;
				}
			}
			synchronized (this) {
				wait();
			}
			return true;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}


	@Override
	public void close() throws Exception {
		zooKeeper.delete(zNnode, -1);
		zooKeeper.close();
		log.info("我已经释放了锁");
	}

	@Override
	public void process(WatchedEvent watchedEvent) {
		if (watchedEvent.getType() == Event.EventType.NodeDeleted) {
			synchronized (this) {
				notify();
			}
		}
	}
}
